<?php

namespace app\index\service;

use app\common\model\CashTransfer;
use app\common\model\Member;
use app\common\model\Transfer;
use app\common\service\TemplateSmsService;
use app\common\service\TransfersServer;
use app\index\dao\CashDao;
use app\index\dao\TransferDao;
use app\index\model\UM as UM;
use app\index\service\payments\AccountPaymentService;
use app\index\service\payments\WxpayPaymentService;
use app\index\traits\PaymentTrait;
use ShidianUtil\Utils\CheckUtil;
use ShidianUtil\Utils\TimeUtil;
use think\exception\ValidateException;
use think\facade\Config;
use think\facade\Log;

/**
 * Class CashService
 * @package app\index\service
 */
class CashService implements TransferableInterface
{
    use PaymentTrait;

    // dao
    private CashDao $cashDao;
    private TransferDao $transferDao;

    public function __construct(CashDao $cashDao, TransferDao $transferDao)
    {
        $this->cashDao = $cashDao;
        $this->transferDao = $transferDao;
    }

    /**
     * 新增
     * @param UM $user
     * @param array $params
     * @return  CashTransfer
     */
    public function add(UM $user, array $params): CashTransfer
    {
        $memberId = $user->id;
        $openidWechat = $user->openidWechat;
        $followedWechat = $user->followedWechat;
        $todaySTime = TimeUtil::stamp(TimeUtil::DAY);
        $todayETime = TimeUtil::stamp(TimeUtil::DAY, $todaySTime, false);

        // 提现金额
        $amount = $params['amount'] ?? null;
        if (!is_numeric($amount)) {
            throw new ValidateException('请输入提现金额');
        }
        $amount = round($amount, 2);

        if ($user->id != 248208 && $user->id != 22155) {
            if ($amount < 100) {
                throw new ValidateException('最低提现金额100元');
            }
        }

        if ($amount > 1000) {
            throw new ValidateException('最高单笔提现金额1000元');
        }

        // 注册满30天才能提现

        // 关注公众号
        if ($followedWechat == 1 && is_blank($openidWechat)) {
            throw new ValidateException('请先关注微信公众号“熊猫法律咨询”，关注后方可进行提现');
        }

        // 不能有进行中的提现
        $cashRecord = CashTransfer::where('memberId', $memberId)
            ->whereIn('status', [0, 1, 2])
            ->find();
        if ($cashRecord) {
            throw new ValidateException('您有提现中的订单，请稍候...');
        }

        // 每天只能申请提现一次
        $cashRecord = CashTransfer::where('memberId', $memberId)
            ->timeRange($todaySTime, $todayETime, 'created', 'created')
            ->find();
        if ($cashRecord) {
            throw new ValidateException('您今天已经申请过提现，请明天再来');
        }

        // 手续费
        $cash_fee_rate = Config::get('site.cash_fee_rate', 0);
        $fee = round($cash_fee_rate * $amount, 2);

        // 计算付款金额
        $payAmount = $amount + $fee;

        if (!$this->getWxpayPaymentService()->isEnableTransfer($memberId)) {
            throw new ValidateException('请关注公众号后提现');
        }

        if (!$this->getAccountPaymentService()->isEnableTransfer($memberId)) {
            throw new ValidateException('您的余额账户暂时不可用，请联系管理员');
        }

        // 余额账户的余额是否充足
        $balance = $this->getAccountPaymentService()->getBalance($memberId);
        if ($balance < $payAmount) {
            throw new ValidateException('您的余额不足，当前余额' . $balance);
        }

        // 创建提现申请
        $data = [
            'memberId' => $memberId,
            'nid' => str_pad(date('YmdHis', time()), 25, '0') . $memberId,
            // 微信转账
            'payMethod' => TRANSFER_WXPAY,
            'openid' => $openidWechat,
            'amount' => $payAmount,
            'total' => $amount,
            'fee' => $fee,
            'payDesc' => Config::get('site.site_name', '') . '零钱提现',
            'status' => 0,
            // 默认审核通过
            'checkStatus' => 1,
            'channel' => 0,
            //强制走微信公众号提现
            'platform' => 5,
        ];

        // 插入提现申请表
        $record = $this->cashDao->insertActive($data, []);

        // 创建支付订单
        $trade = $this->getTradeCashService()->add($user, $record);

        // 立即进行支付
        $this->getPayment($trade->payMethod)->pay($trade, false);

        return $record;
    }

    /**
     * 创建转账申请
     * @param CashTransfer $cashTransfer
     * @return void
     */
    public function createTransfer(CashTransfer $cashTransfer)
    {
        // 进入转账中状态
        $cashTransfer->status = 2;
        $cashTransfer->save();

        $transferType = TRANSFER_CASH;
        $memberId = $cashTransfer->memberId;
        $payMethod = $cashTransfer->payMethod;
        $accountNumber = $cashTransfer->openid;
        $describe = $cashTransfer->payDesc;
        $totalMoney = $cashTransfer->total;
        $append = [
            'cashId' => $cashTransfer->id
        ];
        $this->getTransfersServer()->pushTransferToMember($transferType, $memberId, $payMethod, $accountNumber, $totalMoney, $describe, $append);
    }

    /**
     * 转账完成后的业务逻辑
     * @param Transfer $transfer
     * @return void
     */
    public function completionTransfer(Transfer $transfer): void
    {
        // 写入提现的转账结果
        $cash = CashTransfer::where('id', $transfer->cashId)->where('status', 2)->find();

        if (!$cash) {
            return;
        }

        if ($transfer->transferStatus == '2') {
            $cash->status = '3';
            $cash->paymentNo = $transfer->tradeNid ?? '';
            $cash->save();

            // 给提现人发短信
            $phone = Member::where('id', $cash->memberId)->value('phone');
            if (CheckUtil::isPhoneNumber($phone)) {
                $this->getTemplateSmsService()->cashTransferResult($phone, $cash->total, $cash->created);
            }

        } elseif ($transfer->transferStatus == '3') {
            $cash->status = '4';
            $cash->save();

            Log::error('提现转账失败 cashID=' . $cash->id);

        }

    }

    private function getTradeCashService(): TradeCashService
    {
        return app(TradeCashService::class);
    }

    private function getAccountPaymentService(): AccountPaymentService
    {
        return app(AccountPaymentService::class);
    }

    private function getWxpayPaymentService(): WxpayPaymentService
    {
        return app(WxpayPaymentService::class);
    }

    private function getTemplateSmsService(): TemplateSmsService
    {
        return app(TemplateSmsService::class);
    }

    private function getTransfersServer(): TransfersServer
    {
        return app(TransfersServer::class);
    }
}
